# File cdflib.pyx

"""
This library supports the following operations:
10. Open a CDF file.
20. Close a CDF file.

"""

from cdfh cimport *
import numpy
cimport numpy as numpy_c
from libc.stdlib cimport malloc, free

import cdflib_dict as cdfdict
import cdflib_namedtuple as cdftuple

numpy_c.import_array()

#-----------------------------------------------------------------------
# Global variables.
#-----------------------------------------------------------------------
cdef CDFstatus  _status   # Indicator for CDFlib call.
_current_cdf = ''             # The current CDF file
cdef int _verbose = 5 # Verbose upbound, dprint message with verbose lower than
                      # _verbose will be printed.

# data house-keeping info
cdef enum:
    _VALUE_UNDEFINED = -820318

cdef long _n_zVars  = _VALUE_UNDEFINED # number of zVariables
cdef long _n_rVars  = _VALUE_UNDEFINED # number of rVariables
cdef long _n_Attrs  = _VALUE_UNDEFINED # number of attributes (global + variable)
cdef long _n_gAttrs = _VALUE_UNDEFINED # number of global attributes
cdef long _n_vAttrs = _VALUE_UNDEFINED # number of variable attributes

#-- Item identifiers used for retrieving attributes.
cdef int _gItem = 0  # global 
cdef int _rItem = 1
cdef int _zItem = 2

_rVars = []
_zVars = []
_gAttrs = []  # A list of global attributes.
_vAttrs = []  # A list of variable attributes.



#-----------------------------------------------------------------------
# Utility methods.
#-----------------------------------------------------------------------
def setVerbose(int verbose):
    """Set global verbose upbound.
    
    """
    global _verbose
    _verbose = verbose


def dprint(msg, verbose = 20):
    """ Debug print.  
    
    """
    if verbose <= _verbose:
        print('\n***: %s' % msg)


def status_text(CDFstatus status):
    """Get the status text of a status code.
    
    """
    cdef CDFstatus tmp_status
    cdef char text[CDF_STATUSTEXT_LEN + 1]
    tmp_status = CDFlib(SELECT_, CDF_STATUS_, status, 
            GET_, STATUS_TEXT_, text, 
            NULL_)
    return text


def check_status(CDFstatus status, 
                 gt_msg = None, eq_msg = None, 
                 warn_msg = None, err_msg = None,
                 context = None,
                gt_verbose = 10, warn_verbose = 4):
    if context is None:
        prefix  = ''
    else:
        prefix = '{{ ' + context + ' }} '

    if gt_msg is None:
        gt_msg = prefix + 'Informational -- ' + status_text(status)

    if eq_msg is None:
        eq_msg = prefix + 'Successful -- ' + status_text(status)

    if warn_msg is None:
        warn_msg = prefix + '*** WARNING *** ' + status_text(status)

    if err_msg is None:
        err_msg = prefix + 'ERROR! -- ' + status_text(status)

    if status > CDF_OK:
        dprint(gt_msg, verbose = gt_verbose)
    elif status == CDF_OK:
        dprint(eq_msg)
    elif status > CDF_WARN:
        dprint(warn_msg, verbose = warn_verbose)
    else: 
        raise IOError, err_msg 


def valueName(theDict, theValue, upper = 0, lower = 0):
    for key, value in theDict.iteritems():
        if value == theValue:
            if upper != 0:
                return key.upper()
            elif lower != 0:
                return key.lower()
            else:
                return key
    raise ValueError, 'No value matched in the given dictionary.'
    # End: def valueName(theDict, theValue, upper = 0, lower = 0):

def numpy_dtype(vinfo):
    cdef int dataType = vinfo.dataType
    cdef long numElements = vinfo.numElements
    if dataType in [CDF_CHAR, CDF_UCHAR]: np_dtype = '|S' + str(numElements)
    if dataType in [CDF_BYTE, CDF_INT1]: np_dtype = 'int8'
    if dataType in [CDF_UINT1]: np_dtype = 'uint8'
    if dataType in [CDF_UINT2]: np_dtype = 'uint16'
    if dataType in [CDF_UINT4]: np_dtype = 'uint32'
    if dataType in [CDF_INT2]: np_dtype = 'int16'
    if dataType in [CDF_INT4]: np_dtype = 'int32'
    if dataType in [CDF_REAL4, CDF_FLOAT]: np_dtype = 'float32'
    if dataType in [CDF_REAL8, CDF_DOUBLE, CDF_EPOCH, CDF_EPOCH16]:
        np_dtype = 'float64'
    if dataType in [CDF_TIME_TT2000]: np_dtype = 'int64'
    return np_dtype

def numpy_shape(vinfo):
    # Determine array shape of the real data.
    np_shape = vinfo.dimSizes
    np_shape.insert(0, vinfo.numRecords)
    if vinfo.dataType == CDF_EPOCH16:
        np_shape.append(2)

    return np_shape




#-----------------------------------------------------------------------
# CDF operations.
#-----------------------------------------------------------------------
def open(char *cdfname):
    """
    Open a CDF file. IOError is raised if open failed.

    Required arguments:
    cdfname -- A file path of the CDF file without the '.cdf' extension.

    """
    cdef CDFid file_id # Only used for opening a CDF file.
    global _current_cdf
    _current_cdf = cdfname
    _current_cdf += '.cdf'
    _status = CDFlib(
                    OPEN_, CDF_, cdfname, &file_id,
                    NULL_)
    check_status(_status, context = 'Opening %s' % _current_cdf)


#++++++++++++++++++++++++++++++++++++++++
def close(char *cdfname):
    """Close the current CDF file.

    """

    # Check if the supplied cdfname match the current cdf file.
    cdf_file = cdfname
    cdf_file += '.cdf'
    if cdf_file != _current_cdf:
        raise IOError, 'The specified CDF ' + \
                'file is not the current CDF for CDFlib.'

    # Close CDF.
    _status = CDFlib(CLOSE_, CDF_,
                   NULL_)
    check_status(_status, context = 'Closing %s' % _current_cdf)


#++++++++++++++++++++++++++++++++++++++++
def fileinfo():
    """Get file information, including:
            1. cdf copyright
            4. cdf version
            5. cdf checksum (Normally is NO_CHECKSUM)
            6. format (single-file or mutli-file, currently only single-file is
                        supported.)
            7. majority (row-major or column-major, default is row-major)
            8. compression info
            9. encoding mode (normally is network_encoding, namely, XDR)

    """
    cdef long checksum  
    cdef long cType, cPct, cParms[CDF_MAX_PARMS]   # Compression info
    cdef char copyright[CDF_COPYRIGHT_LEN+1]   # cdf copyright
    cdef long release, version, incre
    cdef long form  # fromat (single-file vs multi-file
    cdef long major # majority (row-major vs column-major)
    cdef long encoding   # normally is network_encoding

    _status = CDFlib(
                    GET_, CDF_CHECKSUM_, &checksum,
                          CDF_COMPRESSION_, &cType, cParms, &cPct,
                          CDF_COPYRIGHT_, copyright,
                          CDF_RELEASE_, &release,
                          CDF_VERSION_, &version,
                          CDF_INCREMENT_, &incre,
                          CDF_FORMAT_, &form,
                          CDF_MAJORITY_, &major,
                          CDF_ENCODING_, &encoding,
                   NULL_)
    check_status(_status, context = 'Retrieving file info')
    compressMode = valueName(cdfdict.compress, cType)
    checksumMode = valueName(cdfdict.checksum, checksum)
    encName      = valueName(cdfdict.encoding, encoding)
    formatName   = valueName(cdfdict.form,     form)
    majorityName = valueName(cdfdict.major,    major)

    # CDF version.
    cdfversion = str(version) + '.' + str(release) + '.' + str(incre)

    info = cdftuple.FileInfo( cdfversion, copyright, compressMode, checksumMode,
                             encName, formatName, majorityName,)
    return info


#++++++++++++++++++++++++++++++++++++++++
def datastats():
    """Get data information, including:
    1. number of zVariables
    2. number of rVariables
    3. number of global attributes
    4. number of variable attributes

    """
    _status = CDFlib(
                    GET_, CDF_NUMATTRS_,  &_n_Attrs,
                          CDF_NUMgATTRS_, &_n_gAttrs,
                          CDF_NUMvATTRS_, &_n_vAttrs,
                          CDF_NUMrVARS_,  &_n_rVars,
                          CDF_NUMzVARS_,  &_n_zVars,
                   NULL_)
    check_status(_status, context = 'Retrieving data info')
    info = cdftuple.DataStats( _n_zVars, _n_rVars, _n_Attrs, _n_gAttrs,
                              _n_vAttrs,)
    return info
        
    
#++++++++++++++++++++++++++++++++++++++++
def varlist():
    """Retrieve a list of all variables in the current CDF file.

    """
    cdef char varName[CDF_VAR_NAME_LEN256+1]
#     global _zVars, _rVars

    if _n_zVars == _VALUE_UNDEFINED: datastats()

    # Get zVars
    if _n_zVars > 0:
        for ii in range(_n_zVars):
            _status = CDFlib(
                            SELECT_, zVAR_, ii,
                            GET_, zVAR_NAME_, varName,
                           NULL_)
            check_status(_status, context = 'Retrieving zVariable names')
            _zVars.append(varName)
    # Get rVars
    if _n_rVars > 0:
        for ii in range(_n_rVars):
            _status = CDFlib(
                            SELECT_, rVAR_, ii,
                            GET_, rVAR_NAME_, varName,
                           NULL_)
            check_status(_status, context = 'Retrieving rVariable names')
            _rVars.append(varName)
    return _zVars + _rVars


def select_var_by_name(char *varName, is_rVar = False):
    cdef int VAR_NAME_
    if is_rVar:
        VAR_NAME_ = rVAR_NAME_
    else:
        VAR_NAME_ = zVAR_NAME_

    _status = CDFlib(
                    SELECT_, VAR_NAME_, varName,
                NULL_)
    check_status(_status, context = 'Selecting %s' % varName)
    

def varinfo(varName, is_rVar=False):
    """Return the following information of the current variable.
    1. data type
    2. row-major or column-major
    3. dimensional size (dimsizes, not applicable to 0-dimensional variable)
    4. dim-varys
    5. number of dimensions
    6. number of elements
    7. number of records
    """ 
    cdef:
        long blockingFactor
        long cType, cParms[CDF_MAX_PARMS], cPct
        long dataType
        long dimSizes[CDF_MAX_DIMS]
        long dimVarys[CDF_MAX_DIMS]
        long varMaxRecAlloc
        long varMaxRec
        long numAllocRecords
        long numDims
        long numElements
        long numRecords
        long recVary

    select_var_by_name(varName)

    pyDimSizes = [] # Python object for dimSizes
    pyDimVarys = [] # Python object for dimVarys, string form
    if is_rVar:
        raise NotImplementedError, 'r-variables are not supported yet.'
    else:
        _status = CDFlib(
                        GET_, zVAR_BLOCKINGFACTOR_  , &blockingFactor,
                              zVAR_DATATYPE_        , &dataType,
                              zVAR_MAXallocREC_     , &varMaxRecAlloc,
                              zVAR_MAXREC_          , &varMaxRec,
                              zVAR_NUMallocRECS_    , &numAllocRecords,
                              zVAR_NUMDIMS_         , &numDims,
                              zVAR_NUMELEMS_        , &numElements,
                              zVAR_NUMRECS_         , &numRecords,
                              zVAR_RECVARY_         , &recVary,
                              zVAR_COMPRESSION_     , &cType, cParms, &cPct,
                     NULL_)
        check_status(_status, context = 'Retrieving variable information.')
        if numDims > 0:
            _status = CDFlib(
                            GET_, zVAR_DIMSIZES_        , dimSizes,
                                  zVAR_DIMVARYS_        , dimVarys,
                           NULL_)
            for i in range(numDims):
                pyDimSizes.append(dimSizes[i])
                pyDimVarys.append(valueName(cdfdict.vary, dimVarys[i]))

    info = cdftuple.VarInfo(
                            blockingFactor,        
                            dataType,
                            varMaxRecAlloc,
                            varMaxRec,
                            numAllocRecords,
                            numDims,
                            numElements,
                            numRecords,
                            recVary,
                            pyDimSizes,
                            pyDimVarys
                           )
    return info
    

#++++++++++++++++++++++++++++++++++++++++
def data(char *varName, is_rVar = False):
    """Retrieve the data of the given variable name. If failed, a NameError is
    raised.

    """
    # If varName is in the CDF file.
    if _n_zVars == _VALUE_UNDEFINED: datastats()
    if not _zVars and not _rVars: varlist()
    if varName not in _zVars and varName not in _rVars: 
        raise NameError, '%s not found in the current CDF file.' % varName

    # Get variable data info
    vinfo = varinfo(varName)

    if vinfo.numRecords == 0:
        raise ValueError, '%s does not contain any data.' % varName

    # Check if row-major or column-major
    finfo = fileinfo()
    if finfo.array_majority == 'COLUMN_MAJOR': 
        raise NotImplementedError, \
            'Sorry, but column-major files are not supported yet.'

    # Get numpy data type and shape.
    np_dtype = numpy_dtype(vinfo)
    np_shape = numpy_shape(vinfo)
    lenData = numpy.array(np_shape).prod() # np = numpy

    # Allocate memory
    cdef numpy_c.ndarray realData = numpy.zeros(np_shape, np_dtype)
    
    # Set number of records to read
    cdef long numRecs = vinfo.numRecords
    _status = CDFlib(
                   SELECT_, zVAR_RECCOUNT_, numRecs,
               NULL_)
    check_status(_status, context = 'Selecting number of records.')

    # Read data
    #-- int2
    if (vinfo.dataType in [CDF_INT2]) and lenData > 0:
        _status = CDFlib(
                       GET_, zVAR_HYPERDATA_, <short int *>realData.data,
                       NULL_)
    #-- uint2
    if (vinfo.dataType in [CDF_UINT2]) and lenData > 0:
        _status = CDFlib(
                   GET_, zVAR_HYPERDATA_, <unsigned short int *>realData.data,
                       NULL_)
    #-- int4
    if (vinfo.dataType in [CDF_INT4]) and lenData > 0:
        _status = CDFlib(
                       GET_, zVAR_HYPERDATA_, <int *>realData.data,
                       NULL_)
    #-- uint4
    if (vinfo.dataType in [CDF_UINT4]) and lenData > 0:
        _status = CDFlib(
                       GET_, zVAR_HYPERDATA_, <unsigned int *>realData.data,
                       NULL_)
    #-- float
    if (vinfo.dataType in [CDF_REAL4, CDF_FLOAT]) and lenData > 0:
        _status = CDFlib(
                       GET_, zVAR_HYPERDATA_, <float *>realData.data,
                       NULL_)
    #-- double
    if (vinfo.dataType in [CDF_REAL8, CDF_DOUBLE, CDF_EPOCH, CDF_EPOCH16]) \
        and lenData > 0:
        _status = CDFlib(
                       GET_, zVAR_HYPERDATA_, <double *>realData.data,
                       NULL_)
    #-- tt2000
    if (vinfo.dataType in [CDF_TIME_TT2000]) and lenData > 0:
        _status = CDFlib(
                       GET_, zVAR_HYPERDATA_, <long long int *>realData.data,
                       NULL_)

    #-- char
    if (vinfo.dataType in [CDF_CHAR]) and lenData > 0:
        _status = CDFlib(
                       GET_, zVAR_HYPERDATA_, <char **>realData.data,
                       NULL_)
    #-- uchar
    if (vinfo.dataType in [CDF_UCHAR]) and lenData > 0:
        _status = CDFlib(
                       GET_, zVAR_HYPERDATA_, <unsigned char **>realData.data,
                       NULL_)
    check_status(_status, context = 'Reading real data.')
    return realData



#++++++++++++++++++++++++++++++++++++++++
def _get_attr_list():
    """Retrieve a list of all attributes.

    """
    # Get a list of all attributes
    # Record scope: global or variable

    # Get attribute scopes and gAttributes
    cdef long iattr, scope
    cdef char attrName[CDF_ATTR_NAME_LEN256+1]
    for iattr in range(0, _n_Attrs):
        _status = CDFlib(
                        SELECT_, ATTR_, iattr,
                       NULL_)
        _status = CDFlib(
                        GET_, ATTR_NAME_, attrName,
                              ATTR_SCOPE_, &scope,
                       NULL_)
        if scope == GLOBAL_SCOPE:
            _gAttrs.append(attrName)
        else:
            _vAttrs.append(attrName)


#++++++++++++++++++++++++++++++++++++++++
def gAttr(char *attrName):
    """Retrieve value of a global attribute.

    """
    # Select the given attribute by name.
    _status = CDFlib(
                    SELECT_, ATTR_NAME_, attrName,
                   NULL_)

    # Get entry data.
    cdef char *dum = 'dum'
    return attrEntries(_gItem, dum)  # varName is not used for gAttr in 
                                     # attrEntries.

def gAttrList():
    if not _gAttrs: _get_attr_list()
    return _gAttrs

def vAttrList():
    if not _vAttrs: _get_attr_list()
    return _vAttrs

#++++++++++++++++++++++++++++++++++++++++
def vAttr(char *attrName, char *varName, is_rVar = False):
    """Retrieve value of a global attribute.

    """
    if is_rVar:
        raise NotImplementedError, 'Sorry, but r-variable is not supported yet.'
    # Select the given attribute by name.
    _status = CDFlib(
                    SELECT_, ATTR_NAME_, attrName,
                   NULL_)

    # Get entry data.
    return attrEntries(_zItem, varName)  # varName is not used for gAttr in 
                                     # attrEntries.

#-------------------------------------------------------------------------------
def attrEntries(int item, char *varName):
    """Get entries of the current attribute.

    Required arguments:
    item    -- Indicator of the entry types. Allowed values are _gItem, _rItem,
               and _zItem.
    varName -- Variable name. Used if item is _rItem or _zItem.
    
    """

    cdef:
        int ENTRY_, ENTRY_DATATYPE_, ENTRY_NUMELEMS_, ENTRY_DATA_
        int ATTR_NUM_ENTRIES_

    entryData = []

    # Determine item type.
    if item == _gItem:
        ENTRY_            = gENTRY_
        ENTRY_DATATYPE_   = gENTRY_DATATYPE_
        ENTRY_NUMELEMS_   = gENTRY_NUMELEMS_
        ENTRY_DATA_       = gENTRY_DATA_
        ATTR_NUM_ENTRIES_ = ATTR_NUMgENTRIES_
    elif item == _rItem:
        ENTRY_NAME_       = rENTRY_NAME_
        ENTRY_DATATYPE_   = rENTRY_DATATYPE_
        ENTRY_NUMELEMS_   = rENTRY_NUMELEMS_
        ENTRY_DATA_       = rENTRY_DATA_
        ATTR_NUM_ENTRIES_ = ATTR_NUMrENTRIES_
    elif item == _zItem:
        ENTRY_NAME_       = zENTRY_NAME_
        ENTRY_DATATYPE_   = zENTRY_DATATYPE_
        ENTRY_NUMELEMS_   = zENTRY_NUMELEMS_
        ENTRY_DATA_       = zENTRY_DATA_
        ATTR_NUM_ENTRIES_ = ATTR_NUMzENTRIES_
    else:
        # Todo: Use exception instead.
        raise ValueError, 'Invalid item value.'

    # Get number of entries.
    cdef long nEntries
    _status = CDFlib(
                    GET_, ATTR_NUM_ENTRIES_, &nEntries,
                   NULL_)

    # Temporary variable to hold entry data.
    cdef:
        char               *charEntry     # CDF_CHAR, CDF_BYTE, CDF_INT1
        unsigned char      *ucharEntry    # CDF_UCHAR, CDF_UINT1
        short int          *int2Entry     # CDF_INT2
        unsigned short int *uint2Entry    # CDF_UINT2
        int                *int4Entry     # CDF_INT4
        unsigned int       *uint4Entry    # CDF_UINT4
        float              *floatEntry    # CDF_REAL4, CDF_FLOAT
        double             *dblEntry      # CDF_REAL8, CDF_DOUBLE, CDF_EPOCH
        double             *epoch16Entry  # CDF_EPOCH16
        long long int      *tt2000Entry   # CDF_TIME_TT2000

    # Loop over all entries.
    cdef long dataType, nElements
    if item == _gItem:
        iRange = range(nEntries)
    else:
        iRange = range(1)
    cdef int i
    for i in iRange:
        # Select the entry.
        if item == _gItem:
            _status = CDFlib(
                           SELECT_, ENTRY_, i,
                           NULL_)
        else:
            _status = CDFlib(
                           SELECT_, ENTRY_NAME_, varName,
                           NULL_)

        # Get data type and length of the entries.
        _status = CDFlib(
                       GET_, ENTRY_DATATYPE_, &dataType,
                             ENTRY_NUMELEMS_, &nElements,
                       NULL_)

        # Allocate memory and get entry data.
        #-- char
        if (dataType in [CDF_CHAR, CDF_BYTE, CDF_INT1]) and nElements > 0:
            charEntry = <char *>malloc(nElements * sizeof(char)+ 1)
            _status = CDFlib(
                           GET_, ENTRY_DATA_, charEntry,
                           NULL_)
            entryData.append(charEntry[:nElements])
            free(charEntry)
        #-- uchar
        if (dataType in [CDF_UCHAR, CDF_UINT1]) and nElements > 0:
            ucharEntry = <unsigned char *>malloc(nElements * sizeof(char)+ 1)
            _status = CDFlib(
                           GET_, ENTRY_DATA_, ucharEntry,
                           NULL_)
            entryData.append(ucharEntry[:nElements])
            free(ucharEntry)
        #-- int2
        if dataType == CDF_INT2 and nElements > 0:
            int2Entry = <short int *>malloc(nElements * sizeof(short int))
            _status = CDFlib(
                           GET_, ENTRY_DATA_, int2Entry,
                           NULL_)
            tmplist = []
            for ii in range(nElements):
                tmplist.append(int2Entry[ii])
            entryData.append(tmplist)
            free(int2Entry)
        #-- uint2
        if dataType == CDF_UINT2 and nElements > 0:
            uint2Entry = <unsigned short int *>malloc( nElements *
                                                  sizeof(unsigned short int))
            _status = CDFlib(
                           GET_, ENTRY_DATA_, uint2Entry,
                           NULL_)
            tmplist = []
            for ii in range(nElements):
                tmplist.append(uint2Entry[ii])
            entryData.append(tmplist)
            free(uint2Entry)
        #-- int4
        if dataType == CDF_INT4 and nElements > 0:
            int4Entry = <int *>malloc(nElements * sizeof(int))
            _status = CDFlib(
                           GET_, ENTRY_DATA_, int4Entry,
                           NULL_)
            tmplist = []
            for ii in range(nElements):
                tmplist.append(int4Entry[ii])
            entryData.append(tmplist)
            free(int4Entry)
        #-- uint4
        if dataType == CDF_UINT4 and nElements > 0:
            uint4Entry = <unsigned int *>malloc(nElements * sizeof(int))
            _status = CDFlib(
                           GET_, ENTRY_DATA_, uint4Entry,
                           NULL_)
            tmplist = []
            for ii in range(nElements):
                tmplist.append(uint4Entry[ii])
            entryData.append(tmplist)
            free(uint4Entry)
        #-- float
        if (dataType in [CDF_REAL4, CDF_FLOAT]) and nElements > 0:
            floatEntry = <float *>malloc(nElements * sizeof(float))
            _status = CDFlib(
                           GET_, ENTRY_DATA_, floatEntry,
                           NULL_)
            tmplist = []
            for ii in range(nElements):
                tmplist.append(floatEntry[ii])
            entryData.append(tmplist)
            free(floatEntry)
        #-- double, real8, epoch
        if (dataType in [CDF_REAL8, CDF_DOUBLE, CDF_EPOCH]) and nElements > 0:
            dblEntry = <double *>malloc(nElements * sizeof(double))
            _status = CDFlib(
                           GET_, ENTRY_DATA_, dblEntry,
                           NULL_)
            tmplist = []
            for ii in range(nElements):
                tmplist.append(dblEntry[ii])
            entryData.append(tmplist)
            free(dblEntry)
        #-- epoch16
        if (dataType in [CDF_EPOCH16]) and nElements > 0:
            epoch16Entry = <double *>malloc(nElements * sizeof(double)*2)
            _status = CDFlib(
                           GET_, ENTRY_DATA_, epoch16Entry,
                           NULL_)
            tmplist = []
            for ii in range(2*nElements):
                tmplist.append(epoch16Entry[ii])
            entryData.append(tmplist)
            free(epoch16Entry)
        #-- tt2000
        if (dataType in [CDF_TIME_TT2000]) and nElements > 0:
            tt2000Entry = <long long int *>malloc(nElements * sizeof(long long
                                                                     int))
            _status = CDFlib(
                           GET_, ENTRY_DATA_, tt2000Entry,
                           NULL_)
            tmplist = []
            for ii in range(nElements):
                tmplist.append(tt2000Entry[ii])
            entryData.append(tmplist)
            free(tt2000Entry)

    if len(entryData) == 1: entryData = entryData[0]
    return entryData
# End: def attrEntries(int item, char *varName):

